﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;

namespace IOFtp
{
    public class ListingDetailsParser
    {
        public static string ExtractDate( string detailRecord )
        {
            #region UNIX LIKE LISTING

            // EXAMPLE OF POSSIBLE LISTINGS THAT CAN BE RESOLVED: 
            // -rw-r--r--    1 ftp      ftp        659450 Jun 15 05:07 TEST.TXT
            // drwxrwxr-x    2 ftp      ftp          4096 May 06 12:24 dropoff

            var match1 = Regex.Match( detailRecord, @"\w{3}\s{1,2}\d{1,2}\s{1,2}\d{1,2}:\d{1,2}" );
            if( match1.Success ) return match1.Value;

            // EXAMPLE OF POSSIBLE LISTINGS THAT CAN BE RESOLVED: 
            // dr-xr-xr-x   1 owner    group               0 Nov 25  2002 bussys
            // d--x--x--x    2 ftp      ftp          4096 Mar 07  2002 bin
            // -rw-r--r--    1 ftp      ftp      101786380 Sep 08  2008 TEST03-05.TXT

            var match2 = Regex.Match( detailRecord, @"\w{3}\s{1,2}\d{1,2}\s{1,2}\d{4}" );
            if( match2.Success ) return match2.Value;

            #endregion

            #region WINDOWS LIKE LISTING

            // EXAMPLE OF POSSIBLE LISTINGS THAT CAN BE RESOLVED: 
            // 02-03-04  07:46pM       <DIR>          Append
            // 08-10-11  12:02am       <DIR>          Version2
            // 06-25-09   02:41AM            144700153 image34.gif
            // 06-25-09     02:51PM            144700153 updates.txt
            // 11-04-10  02:45PM            144700214 digger.tif

            var match3 = Regex.Match( detailRecord, @"\d{1,2}-\d{1,2}-\d{1,2}\s+\d{1,2}:\d{1,2}(PM|pm|AM|am)" );
            if( match3.Success ) return match3.Value;

            #endregion

            throw new Exception( "Could not extract date: unknown listing format." );
        }

        public static string ExtractObjectName( string detailRecord )
        {
            #region UNIX LIKE LISTING

            // EXAMPLE OF POSSIBLE LISTINGS THAT CAN BE RESOLVED: 
            // -rw-r--r--    1 ftp      ftp        659450 Jun 15 05:07 TEST.TXT
            // drwxrwxr-x    2 ftp      ftp          4096 May 06 12:24 dropoff

            var match1 = Regex.Match( detailRecord, @"\w{3}\s{1,2}\d{1,2}\s{1,2}\d{1,2}:\d{1,2}" );
            if( match1.Success ) return detailRecord.Substring( match1.Index + match1.Length ).Trim();

            // EXAMPLE OF POSSIBLE LISTINGS THAT CAN BE RESOLVED: 
            // dr-xr-xr-x   1 owner    group               0 Nov 25  2002 bussys
            // d--x--x--x    2 ftp      ftp          4096 Mar 07  2002 bin
            // -rw-r--r--    1 ftp      ftp      101786380 Sep 08  2008 TEST03-05.TXT

            var match2 = Regex.Match( detailRecord, @"\w{3}\s{1,2}\d{1,2}\s{1,2}\d{4}" );
            if( match2.Success ) return detailRecord.Substring( match2.Index + match2.Length ).Trim();

            #endregion

            #region WINDOWS LIKE LISTING

            // EXAMPLE OF POSSIBLE LISTINGS THAT CAN BE RESOLVED: 
            // 02-03-04  07:46pM       <DIR>          Append
            // 08-10-11  12:02am       <DIR>          Version2
            // 06-25-09  02:41AM            144700153 image34.gif
            // 06-25-09  02:51PM            144700153 updates.txt
            // 11-04-10  02:45PM            144700214 digger.tif

            var match3 = Regex.Match( detailRecord, @"\d{9}" );
            if( match3.Success ) return detailRecord.Substring( match3.Index + match3.Length ).Trim();

            #endregion

            throw new Exception( "Could not extract directory or file name: unknown listing format." );
        }
    }

    /*
    public struct FileStruct
    {
        public string Flags;
        public string Owner;
        public string Group;
        public bool IsDirectory;
        public DateTime CreateTime;
        public string Name;
    }
    public enum FileListStyle
    {
        UnixStyle,
        WindowsStyle,
        Unknown
    }

    class DetailsListParser
    {
        static void Main( string[] args )
        {
            if( args.Length < 1 )
            {
                Console.WriteLine( "\n Usage FTPListDirParser <uriString>" );
                return;
            }
            try
            {
                FtpWebRequest ftpclientRequest = WebRequest.Create( args[ 0 ] ) as FtpWebRequest;
                ftpclientRequest.Method = FtpMethods.ListDirectoryDetails;
                ftpclientRequest.Proxy = null;
                FtpWebResponse response = ftpclientRequest.GetResponse() as FtpWebResponse;
                StreamReader sr = new StreamReader( response.GetResponseStream(), System.Text.Encoding.ASCII );
                string Datastring = sr.ReadToEnd();
                response.Close();

                FileStruct[] list = ( new ParseListDirectory() ).GetList( Datastring );
                Console.WriteLine( "------------After Parsing-----------" );
                foreach( FileStruct thisstruct in list )
                {
                    if( thisstruct.IsDirectory )
                        Console.WriteLine( "<DIR> " + thisstruct.Name + "," + thisstruct.Owner + "," + thisstruct.Flags + "," + thisstruct.CreateTime );
                    else
                        Console.WriteLine( thisstruct.Name + "," + thisstruct.Owner + "," + thisstruct.Flags + "," + thisstruct.CreateTime );
                }
            }
            catch( Exception e )
            {
                Console.WriteLine( e );
            }
        }

        private FileStruct[] GetList( string datastring )
        {
            List<FileStruct> myListArray = new List<FileStruct>();
            string[] dataRecords = datastring.Split( '\n' );
            FileListStyle _directoryListStyle = GuessFileListStyle( dataRecords );
            foreach( string s in dataRecords )
            {
                if( _directoryListStyle != FileListStyle.Unknown && s != "" )
                {
                    FileStruct f = new FileStruct();
                    f.Name = "..";
                    switch( _directoryListStyle )
                    {
                        case FileListStyle.UnixStyle:
                            f = ParseFileStructFromUnixStyleRecord( s );
                            break;
                        case FileListStyle.WindowsStyle:
                            f = ParseFileStructFromWindowsStyleRecord( s );
                            break;
                    }
                    if( !( f.Name == "." || f.Name == ".." ) )
                    {
                        myListArray.Add( f );
                    }
                }
            }
            return myListArray.ToArray(); ;
        }

        private FileStruct ParseFileStructFromWindowsStyleRecord( string Record )
        {
            ///Assuming the record style as 
            /// 02-03-04  07:46PM       <DIR>          Append
            FileStruct f = new FileStruct();
            string processstr = Record.Trim();
            string dateStr = processstr.Substring( 0, 8 );
            processstr = ( processstr.Substring( 8, processstr.Length - 8 ) ).Trim();
            string timeStr = processstr.Substring( 0, 7 );
            processstr = ( processstr.Substring( 7, processstr.Length - 7 ) ).Trim();
            f.CreateTime = DateTime.Parse( dateStr + " " + timeStr );
            if( processstr.Substring( 0, 5 ) == "<DIR>" )
            {
                f.IsDirectory = true;
                processstr = ( processstr.Substring( 5, processstr.Length - 5 ) ).Trim();
            }
            else
            {
                string[] strs = processstr.Split( new char[] { ' ' }, true );
                processstr = strs[ 1 ].Trim();
                f.IsDirectory = false;
            }
            f.Name = processstr;  //Rest is name   
            return f;
        }


        public FileListStyle GuessFileListStyle( string[] recordList )
        {
            foreach( string s in recordList )
            {
                if( s.Length > 10
                 && Regex.IsMatch( s.Substring( 0, 10 ), "(-|d)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)" ) )
                {
                    return FileListStyle.UnixStyle;
                }
                else if( s.Length > 8
                 && Regex.IsMatch( s.Substring( 0, 8 ), "[0-9][0-9]-[0-9][0-9]-[0-9][0-9]" ) )
                {
                    return FileListStyle.WindowsStyle;
                }
            }
            return FileListStyle.Unknown;
        }

        private FileStruct ParseFileStructFromUnixStyleRecord( string Record )
        {
            ///Assuming record style as
            /// dr-xr-xr-x   1 owner    group               0 Nov 25  2002 bussys
            FileStruct f = new FileStruct();
            string processstr = Record.Trim();
            f.Flags = processstr.Substring( 0, 9 );
            f.IsDirectory = ( f.Flags[ 0 ] == 'd' );
            processstr = ( processstr.Substring( 11 ) ).Trim();
            _cutSubstringFromStringWithTrim( ref processstr, ' ', 0 );   //skip one part
            f.Owner = _cutSubstringFromStringWithTrim( ref processstr, ' ', 0 );
            f.Group = _cutSubstringFromStringWithTrim( ref processstr, ' ', 0 );
            _cutSubstringFromStringWithTrim( ref processstr, ' ', 0 );   //skip one part
            f.CreateTime = DateTime.Parse( _cutSubstringFromStringWithTrim( ref processstr, ' ', 8 ) );
            f.Name = processstr;   //Rest of the part is name
            return f;
        }

        private string _cutSubstringFromStringWithTrim( ref string s, char c, int startIndex )
        {
            int pos1 = s.IndexOf( c, startIndex );
            string retString = s.Substring( 0, pos1 );
            s = ( s.Substring( pos1 ) ).Trim();
            return retString;
        }
    }*/
}
